﻿#include "StaticTextArranger.h"
#include "Font/Font.h"
#include "Font/Glyph.h"
#include "Font/FontSubsystem.h"
#include "Framework/Application.h"

#include "Output/Console.h"

#include "Time/CPUTimeCounter.h"

void CStaticTextArranger::ArrangeText(const STextArrangePapameters &InParameters)
{
    CODE_BLOCK_TIME_COUNT(U"排版文本")

    if(Result.Parameters==InParameters)
    {
        return;
    }
    Result.Parameters=InParameters;

    if(InParameters.Text.IsEmpty())
    {
        Result=SArrangedText();
        Result.LineHeight=InParameters.Font->GetLineHeight(InParameters.FontSize);
        return;
    }

    Result.LineHeight=InParameters.Font->GetLineHeight(InParameters.FontSize);
    
    
    //填充字符结构体
    Result.Chars.Clear(false);
    Result.Chars.Reserve(InParameters.Text.GetLength());
    for(int32_t CharIndex=0;CharIndex< InParameters.Text.GetLength();CharIndex++)
    {
        auto& CurrentChar=Result.Chars.Emplace();
        CurrentChar.Char=InParameters.Text[CharIndex];
        CurrentChar.IsNewLine=CurrentChar.Char==U'\n';
    }

    //填充行结构体
    Result.Lines.Clear(false);

    Result.Lines.Emplace();
    Result.Lines[0].StartCharIndex=0;
    int32_t CurrentLineIndex=0;

    bool bIsWrapByWidth=InParameters.Wrap==ETextWrapMethod::WrapByWidth||InParameters.Wrap==ETextWrapMethod::WrapByWidthAndAtLineEnd;
    bool bIsWrapAtLineEnd=InParameters.Wrap==ETextWrapMethod::WrapAtLineEnd||InParameters.Wrap==ETextWrapMethod::WrapByWidthAndAtLineEnd;
    for(int32_t CharIndex=0;CharIndex< InParameters.Text.GetLength();CharIndex++)
    {
        auto& CurrentChar=Result.Chars[CharIndex];
        if(CurrentChar.IsNewLine)
        {
            //尝试换行，对于不允许换行的情况，直接丢弃换行符以及之后的字符
            //换行符本身被看做是上一行的最后一个字符
            if(bIsWrapAtLineEnd)
            {
                Result.Lines[CurrentLineIndex].EndCharIndex=CharIndex;
                
                if((CharIndex+1)<InParameters.Text.GetLength())
                {
                    //生成新的行
                    Result.Lines.Emplace();
                    CurrentLineIndex++;

                    Result.Lines[CurrentLineIndex].StartCharIndex=CharIndex+1;

                }
                continue;
            }
            else
            {
                //不允许多行
                //直接丢弃换行符以及之后的字符
                break;
            }
        }
    }
    Result.Lines.Last().EndCharIndex=InParameters.Text.GetLength()-1;

    //计算行宽，此时不考虑分散对齐
    for(int32_t LineIndex=0;LineIndex<Result.Lines.Num();LineIndex++)
    {
        auto& Line=Result.Lines[LineIndex];
        Line.Width=0;

        for(int32_t CharIndex=Line.StartCharIndex;CharIndex<=Line.EndCharIndex;CharIndex++)
        {
            auto& Char=Result.Chars[CharIndex];
            auto Glyph=InParameters.Font->SupportChar(Char.Char) ? 
                InParameters.Font->FindOrCreateGlyph(Char.Char,InParameters.FontSize)
                :
                RApplication::GetApplication()->GetSubsystem<RFontApplicationSubsystem>()->GetFallBackFont()
                ->FindOrCreateGlyph(Char.Char,InParameters.FontSize)
                ;

            Char.Glyph=Glyph;
            //这个字符占用的宽度，包括白边
            float CharSpan=Glyph->AdvanceX; 

            //当超出最大行宽时尝试换行
            float NewWidth=Line.Width+CharSpan;
            if(bIsWrapByWidth 
            && NewWidth>InParameters.PaintAreaSize.X
            && Line.EndCharIndex!=CharIndex //当行只有一个字符时，不允许换行，否则会有无数行
            )
            {
                //超出宽度，再插入一行
                SLineRenderInfo NewLine;
                NewLine.StartCharIndex=CharIndex;
                NewLine.EndCharIndex=Line.EndCharIndex;

                Line.EndCharIndex=CharIndex-1;

                Result.Lines.Insert(LineIndex+1,NewLine);

                continue;
            }

            Line.Width+=CharSpan;
        }
    }

    //计算行相对于绘制区域的X
    switch(InParameters.HorizontalAlign)
    {
        case ETextHorizontalAlignment::Left:
        case ETextHorizontalAlignment::Scatter:
        {
            //行的X位置为默认值0
            break;
        }

        case ETextHorizontalAlignment::Center:
        {
            for(auto& Line: Result.Lines)
            {
                Line.XInRenderArea=(InParameters.PaintAreaSize.X-Line.Width)*.5f;
            }
            break;
        }

        case ETextHorizontalAlignment::Right:
        {
            for(auto& Line: Result.Lines)
            {
                Line.XInRenderArea=InParameters.PaintAreaSize.X-Line.Width;
            }
            break;
        }

    }

    //计算字符在行中的X位置
    switch(InParameters.HorizontalAlign)
    {
        case ETextHorizontalAlignment::Left:
        case ETextHorizontalAlignment::Center:
        case ETextHorizontalAlignment::Right:
        {
            for(auto& Line: Result.Lines)
            {
                float PenX=0;
                for(int32_t CharIndex=Line.StartCharIndex;CharIndex<=Line.EndCharIndex;CharIndex++)
                {
                    auto& Char=Result.Chars[CharIndex];
                    //字符位置和大小
                    Char.OcuppiedWidth=Char.Glyph->AdvanceX;
                    Char.OcuppiedRectMinX=PenX;
                    //字符图片的位置
                    Char.TextureXInLine=PenX+ Char.Glyph->Box.Min.X;
                    PenX+=Char.Glyph->AdvanceX;
                }
            }
            break;
        }

        case ETextHorizontalAlignment::Scatter:
        {
            for(auto& Line: Result.Lines)
            {
                if(Line.StartCharIndex==Line.EndCharIndex)
                {
                    //只有一个字符，把字符图片放在中间，字符宽度=AdvanceX
                    float CharOccupiedWidth=Result.Chars[Line.StartCharIndex].Glyph->AdvanceX;
                    float BlankWidthBeforeChar=(InParameters.PaintAreaSize.X-CharOccupiedWidth)/2;

                    auto& Char=Result.Chars[Line.StartCharIndex];
                    Char.OcuppiedRectMinX=BlankWidthBeforeChar;
                    Char.OcuppiedWidth=CharOccupiedWidth;

                    Result.Chars[Line.StartCharIndex].TextureXInLine=Char.OcuppiedRectMinX+ Char.Glyph->Box.Min.X;
                    continue;
                }

                float PenX=Line.XInRenderArea;
                float BlankWidthAfterChar=(InParameters.PaintAreaSize.X-Line.Width)/(Line.EndCharIndex-Line.StartCharIndex);
                for(int32_t CharIndex=Line.StartCharIndex;CharIndex<=Line.EndCharIndex;CharIndex++)
                {
                    auto& Char=Result.Chars[CharIndex];
                    Char.OcuppiedRectMinX=PenX;
                    Char.OcuppiedWidth=Char.Glyph->AdvanceX+BlankWidthAfterChar;

                    Char.TextureXInLine=PenX+ Char.Glyph->Box.Min.X ;
                    PenX+=Char.Glyph->AdvanceX+BlankWidthAfterChar;
                }

                //修正行的宽度
                Line.Width=Line.XInRenderArea;
            }
            break;
        }
    }


    //计算行的Y位置
    switch(InParameters.VerticalAlign)
    {
        case ETextVerticalAlignment::Top:
        {
            float PenY=0;
            for(auto& Line: Result.Lines)
            {
                Line.YInRenderArea=PenY;
                PenY+=Result.LineHeight;
            }
            break;
        }

        case ETextVerticalAlignment::Center:
        {
            float TotalHeight=Result.Lines.Num()*Result.LineHeight;
            float PenY=(InParameters.PaintAreaSize.Y-TotalHeight)*.5f;
            for(auto& Line: Result.Lines)
            {
                Line.YInRenderArea=PenY;
                PenY+=Result.LineHeight;
            }
            break;
        }

        case ETextVerticalAlignment::Bottom:
        {
            float PenY=InParameters.PaintAreaSize.Y-Result.LineHeight;
            for(auto& Line: Result.Lines)
            {
                Line.YInRenderArea=PenY;
                PenY-=Result.LineHeight;
            }
            break;
        }
    }

    //计算字符图片在行中的Y位置
    auto TopLineHeight=InParameters.Font->GetAscent(InParameters.FontSize);
    for(auto& Char: Result.Chars)
    {
        if(Char.Glyph)
        {
            Char.TextureYInLine=TopLineHeight-(Char.Glyph->Box.Min.Y+Char.Glyph->Box.Extent.Y);
        }
    }

    //计算整个文本的图片大小和位置
    // SVec2 WholeImageBoxMin,WholeImageBoxMax;
    // WholeImageBoxMin.X=std::numeric_limits<float>::max();
    // WholeImageBoxMin.Y=std::numeric_limits<float>::max();
    // WholeImageBoxMax.X=-std::numeric_limits<float>::max();
    // WholeImageBoxMax.Y=-std::numeric_limits<float>::max();

    for(auto& Line: Result.Lines)
    {
        for(int32_t CharIndex=Line.StartCharIndex;CharIndex<=Line.EndCharIndex;CharIndex++)
        {
            auto& Char=Result.Chars[CharIndex];
            //if(Char.Glyph)
            {
                //一些特殊字符不需要渲染，比如'\n',但是字体可能依然会提供一张图片
                //需要手动屏蔽
                if(Char.Char==U'\n')
                {
                    continue;
                }

                Char.Texture=Char.Glyph->LoadTexture();
                // if(!Char.Texture)
                // {
                //     //空格等字符没有图片
                //     continue;
                // }

                // //文字图片在整个绘制区域中的位置
                // float CharPostionInRenderAreaX=Char.TextureXInLine+Line.XInRenderArea;
                // float CharPostionInRenderAreaY=Char.TextureYInLine+Line.YInRenderArea;
                // float CharWidth=Char.Glyph->Box.Extent.X;
                // float CharHeight=Char.Glyph->Box.Extent.Y;

                // WholeImageBoxMin.X=CMathBase::Min(WholeImageBoxMin.X,CharPostionInRenderAreaX);
                // WholeImageBoxMin.Y=CMathBase::Min(WholeImageBoxMin.Y,CharPostionInRenderAreaY);

                // WholeImageBoxMax.X=CMathBase::Max(WholeImageBoxMax.X,CharPostionInRenderAreaX+CharWidth);
                // WholeImageBoxMax.Y=CMathBase::Max(WholeImageBoxMax.Y,CharPostionInRenderAreaY+CharHeight);
            }
        }
    }

//     //创建整个文本的图片
//     Result.WholeImageOffset=WholeImageBoxMin;
//     Result.WholeImageSize=WholeImageBoxMax-WholeImageBoxMin;
//     TVector<uint8_t> TextData;
//     TextData.Resize(1 * Result.WholeImageSize.X * Result.WholeImageSize.Y);
//     int32_t WholeImagePitch=1 *Result.WholeImageSize.X;

//     Result.WholeImage=TSharedObjectPtr<RTexture2D>(RTexture2D::CreateFromRawData(
//         std::move(TextData)
//         ,WholeImagePitch
//         ,Result.WholeImageSize
//         ,ETextureFormat::R8
//         ,nullptr
//     ));

//     //填充整个文本的图片
//     for(auto& Line: Result.Lines)
//     {
//         for(int32_t CharIndex=Line.StartCharIndex;CharIndex<=Line.EndCharIndex;CharIndex++)
//         {
//             auto& Char=Result.Chars[CharIndex];
//             if(Char.Texture)
//             {
//                 //文字图片在整个绘制区域中的位置
//                 float CharPostionInRenderAreaX=Char.TextureXInLine+Line.XInRenderArea;
//                 float CharPostionInRenderAreaY=Char.TextureYInLine+Line.YInRenderArea;
//                 float CharWidth=Char.Glyph->Box.Extent.X;
//                 float CharHeight=Char.Glyph->Box.Extent.Y;

//                 float CharXInWholeImage=CharPostionInRenderAreaX-WholeImageBoxMin.X;
//                 float CharYInWholeImage=CharPostionInRenderAreaY-WholeImageBoxMin.Y;
//                 Char.OffsetXInWholeImage=CharXInWholeImage;
//                 Char.OffsetYInWholeImage=CharYInWholeImage;

//                 for(int32_t Y=0;Y<Char.Glyph->Box.Extent.Y;Y++)
//                 {
//                     for(int32_t X=0;X<Char.Glyph->Box.Extent.X;X++)
//                     {
//                         int64_t WholeImageRow=CharYInWholeImage+Y;
//                         assert(WholeImageRow>=0 && WholeImageRow<Result.WholeImageSize.Y);
//                         int64_t WholeImageCol=CharXInWholeImage+X;
//                         assert(WholeImageCol>=0 && WholeImageCol<Result.WholeImageSize.X);

//                         int32_t WholeImageDataIndex=WholeImageRow*WholeImagePitch+WholeImageCol;
//                         int32_t CharTextureDataIndex=Y*Char.Texture->GetPitch()+X;
//                         Result.WholeImage->Data.Data()[WholeImageDataIndex]=Char.Texture->Data.Data()[CharTextureDataIndex];
//                     }
//                 }
//             }
//         }
//     }
//     Result.WholeImage->SyncToRenderThread();

// //#define DEBUG_TEXT_TEXTURE 1
// #ifdef DEBUG_TEXT_TEXTURE
//     //调试代码，输出图片
//     WH::PrintLine(U"Debug Text image:");
//     for(int32_t Y=0;Y<Result.WholeImageSize.Y;Y++)
//     {
//         for(int32_t X=0;X<Result.WholeImageSize.X;X++)
//         {
//             int32_t WholeImageDataIndex=Y*WholeImagePitch+X;
//             uint8_t Value=Result.WholeImage->Data.Data()[WholeImageDataIndex];
//             if(Value>0)
//             {
//                 WH::Print(U"X");
//             }
//             else
//             {
//                 WH::Print(U" ");
//             }
//         }
//         WH::PrintLine(U"");
//     }


// #endif
}

